// ==============================================================
// This part of the code defines the default values and global values
// ==============================================================

let zg = null;
let isChecked = false;
let isLogin = false;
let localStream = null; // 当前在推的一条流
let remoteStream = null; // 当前在拉的一条流
let published = false; // 推流状态
let played = false;
let mikeClose = false; // 麦克风静音
let videoCodec = localStorage.getItem('VideoCodec') === 'H.264' ? 'H264' : 'VP8';

// part end

// ==============================================================
// 这部分代码使用SDK
// ==============================================================

// 初始化
function createZegoExpressEngine() {
    zg = new ZegoExpressEngine(appID, server);
    window.zg = zg;
}

// 检查系统要求
async function checkSystemRequirements() {
    try {
        const result = await zg.checkSystemRequirements();
        console.warn('checkSystemRequirements ', result);

        if (!result.webRTC) {
            console.error('browser is not support webrtc!!');
            return false;
        } else if (!result.videoCodec.H264 && !result.videoCodec.VP8) {
            console.error('browser is not support H264 and VP8');
            return false;
        } else if (!result.camera && !result.microphones) {
            console.error('camera and microphones not allowed to use');
            return false;
        } else if (result.videoCodec.VP8) {
            if (!result.screenSharing) console.warn('browser is not support screenSharing');
        } else {
            console.log('不支持VP8，请前往混流转码测试');
        }
        return true;
    } catch (err) {
        console.error('checkSystemRequirements', err);
        return false;
    }
}

// 登录房间
async function loginRoom(roomId, userId, userName, token) {
    return await zg.loginRoom(roomId, token, {
        userID: userId
    });
}

// 登出房间
async function logoutRoom(roomId) {
    isLogin = false;
    return await zg.logoutRoom(roomId);
}

// 输出内容
function alerts(content) {
    // alert(content);
    console.log(content);
}

// 房间各类回调动作
function initEvent() {
    // 房间状态更新回调，登录房间后，当房间连接状态发生变更（如出现房间断开，登录认证失败等情况），SDK 会通过该回调通知。
    zg.on('roomStateUpdate', (roomId, state) => {
        // 房间连接成功
        if (state === 'CONNECTED' && isLogin) {
            alerts('房间连接成功');
        }
        // 房间断开
        if (state === 'DISCONNECTED' && !isLogin) {
            alerts('房间断开');
        }
        // 房间断开
        if (state === 'DISCONNECTED' && isLogin) {
            location.reload()
        }
        // 踢出
        if (state === 'onKickOut' && isLogin) {

        }
    })

    // 流状态更新回调，登录房间后，当房间内有用户新推送或删除音视频流时，SDK 会通过该回调通知。
    zg.on('roomStreamUpdate', async (roomID, updateType, streamList, extendedData) => {
        if (updateType === 'ADD') {
            // 房间内出现新数据流时直接接入
            const addStream = streamList[streamList.length - 1]
            if (addStream && addStream.streamID) {
                // 校验新流是否存在，已存在则先断开
                var video_id = 'playVideo' + addStream.streamID
                if ($('#'+video_id).length > 0) {
                    await stopPlayingStream(addStream.streamID)
                }
                await startPlayingStream(addStream.streamID);
                get_room_user(); // 更新用户列表
                alerts('流进入'+addStream.streamID);
            }
        } else if (updateType === 'DELETE') {
            // 数据流退出、离开
            const delStream = streamList[streamList.length - 1]
            if (delStream && delStream.streamID) {
                await stopPlayingStream(delStream.streamID)
                get_room_user(); // 更新用户列表
                alerts('流离开'+delStream.streamID);
            }
        }
    });

    // 推流状态更新回调，调用推流接口成功后，当推流状态发生变更，如出现网络中断导致推流异常等情况，SDK 在重试推流的同时，会通过该回调通知。
    zg.on('publisherStateUpdate', (result) => {
        console.warn('publisherStateUpdate', result);
        if (result.state === 'PUBLISHING') {
            // result.streamID
        } else if (result.state === 'NO_PUBLISH') {
            alerts('推流状态异常');
        }
    });

    // 拉流状态更新回调，调用拉流接口成功后，当拉流状态发生变更，如出现网络中断导致推流异常等情况，SDK 在重试拉流的同时，会通过该回调通知。
    zg.on('playerStateUpdate', (result) => {
        console.warn('playerStateUpdate', result);
        if (result.state === 'PLAYING') {
            // result.streamID
        } else if (result.state === 'NO_PLAY') {
            // 有人关闭连麦
            alerts('拉流状态异常'+result.streamID);
        }
    });

    // 推流质量回调。调用推流接口成功后，定时回调音视频流质量数据（如分辨率、帧率、码率等）。
    zg.on('publishQualityUpdate', (streamId, stats) => {
        console.warn('publishQualityUpdate', streamId, stats);
    });

    // 拉取音视频流时的质量回调。调用拉流接口成功后，您会定时收到拉取音视频流时的质量数据通知（如分辨率、帧率、码率等）。
    zg.on('playQualityUpdate', (streamId, stats) => {
        console.warn('playQualityUpdate', streamId, stats);
    });
    zg.on('screenSharingEnded', (stream) => {
        console.warn('screen sharing end');
    });
}

// 开始视频推流
async function startPublishingStream(streamId, config) {
    try {
        localStream = await zg.createStream(config);
        zg.zegoWebRTC.rtcModules.streamCenter.isPeer = false;
        zg.startPublishingStream(streamId, localStream, { videoCodec });
        $('#publishVideo')[0].srcObject = localStream;
        return true;
    } catch (err) {
        return false;
    }
}

// 开始音频推流
async function startAudioPublishingStream(streamId, config) {
    try {
        localStream = await zg.createStream(config);
        zg.startPublishingStream(streamId, localStream, { videoCodec });
        return true;
    } catch (err) {
        return false;
    }
}

// 停止将本地流推送到远端（即构服务器）
async function stopPublishingStream(streamId) {
    zg.stopPublishingStream(streamId);
    // 同时停止其余全部拉流
}

// （连麦）开始拉流
async function startPlayingStream(streamId, options = {}) {
    try {
        if (options === {}) {
            options = {
                video: false,
                audio: undefined,
                videoCodec: 'VP8'
            };
        }
        remoteStream = await zg.startPlayingStream(streamId, options);
        var video_id = 'playVideo' + streamId
        var video_tap = '<video controls id="'+ video_id +'" autoplay playsinline style="display: none;"></video>';
        $('.paly-video').append(video_tap);
        $('#'+video_id)[0].srcObject = remoteStream;
        return true;
    } catch (err) {
        return false;
    }
}
// （连麦）停止拉流
async function stopPlayingStream(streamId, options = {}) {
    try {
        await zg.stopPlayingStream(streamId);
        var video_id = 'playVideo' + streamId;
        $('#'+video_id).remove();
        return true;
    } catch (err) {
        return false;
    }
}

// 登录房间
async function adminLoginRoom() {
    if (!userID) return alerts('userID is Empty');
    if (!roomID) return alerts('RoomID is Empty');

    if (!isLogin) {
        try {
            isLogin = true;
            await loginRoom(roomID, userID, userID, token);
            // updateButton(this, 'Login Room', 'Logout Room');

        } catch (err) {
            isLogin = false;
            alerts('登录失败，请刷新页面后重试');
        }
    }
}

// uses SDK end

// ==============================================================
// 这部分代码绑定了button click事件
// ==============================================================

// 选择屏幕并推流开始推流
$('#startPublishing').on(
    'click',
    util.throttle(async function () {
        if (!publishVideoStreamid) return alerts('PublishID is empty');
        if (!published) {
            // 开始推流
            const flag = await startPublishingStream(publishVideoStreamid, getCreateStreamConfig());
            if (flag) {
                published = true;
                const flag_audio = await startAudioPublishingStream(publishAudioStreamid, getCreateAudioStreamConfig());
                if (!flag_audio) {
                    swal ('音频推流失败', '请刷新页面后重试', 'error');
                }
                $(this).hide();
                $('#stopLive').show();
            }
        } else {
            // 结束推流
            await stopPublishingStream(publishVideoStreamid);
            await stopPublishingStream(publishAudioStreamid);
            published = false;
        }
    }, 500)
);

// 结束会议
$('#stopLive').on(
    'click',
    util.throttle(async function () {
        swal({
            title: '确认结束',
            text: '',
            icon: 'warning',
            dangerMode: true,
            buttons: ["取消", "确认"],
        })
        .then(async function (willDelete) {

            if (willDelete) {
                if (localStream) {
                    // updateButton($('#startPublishing')[0], 'Start Publishing', 'Stop Publishing');
                }
                await stopPublishingStream(publishVideoStreamid);
                await stopPublishingStream(publishAudioStreamid);
                published = false;
                await logoutRoom(roomID);
                isLogin = false;
                $('#publishVideo')[0].srcObject = null;
                $('#stopLive').hide();
                end_meeting(); // 结束会议，修改会议状态
            }
        });
    }, 500)
);


// 麦克风静音
$('#mikeClose').on(
    'click',
    util.throttle(async function () {
        await zg.muteMicrophone(!mikeClose);
        mikeClose = !mikeClose;

        if (mikeClose === true) {
            $(this).find('i').attr('class', 'feather icon-mic-off');
        } else {
            $(this).find('i').attr('class', 'feather icon-mic');
        }
    }, 500)
);

// bind event end

// ==============================================================
// This part of the code bias tool
// ==============================================================

// 设置共享桌面视频推流参数
function getCreateStreamConfig() {
    const config = {
        screen: {
            audio: true,
            bitrate: 3000,
            frameRate: 20,
            width: 1080,
            height: 720,
            videoQuality: 4,
            startBitrate: 'target'
        }
    };
    return config;
}

// 音频推流参数
function getCreateAudioStreamConfig() {
    const config = {
        camera: {
            /**
             *  视频质量等级，默认质量等级为 2：1：分辨率 320 * 240，帧率 15，码率 300 kbps
             2：分辨率 640 * 480，帧率:15，码率 800 kbps
             3：分辨率 1280 * 720，帧率:20，码率 1500 kbps
             4：分辨率 width * height，帧率 frameRate，码率: bitrate（kbps）
             注：当 videoQuality 为 4 时，width、height、frameRate 和 bitrate 四个参数必填。
             */
            // videoQuality: 2,
            // audioBitrate: 48, // 音频码率，默认为 48kbps
            audioInput: 'default',
            videoInput: '',
            video: false,
            audio: true
        }
    };
    return config;
}

// tool end

// ==============================================================
// This part of the code Initialization web page
// ==============================================================

async function render() {
    createZegoExpressEngine(); // 初始化
    await checkSystemRequirements(); // 检查系统要求
    initEvent(); // 房间各类回调动作
    await adminLoginRoom(); // 登录房间
}

render();

// Initialization end
